package com.hawthorn.admin.service.sysdict.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hawthorn.admin.feign.redisService.RedisDictFeignService;
import com.hawthorn.admin.model.po.SysDictPO;
import com.hawthorn.admin.repository.SysDictMapper;
import com.hawthorn.admin.service.sysdict.SysDictService;
import com.hawthorn.component.utils.bean.Map2ObjUtil;
import com.hawthorn.platform.exception.BizCode;
import com.hawthorn.platform.service.TransResultService;
import com.hawthorn.platform.utils.common.MyUtil;
import com.hawthorn.platform.utils.iassert.AssertMyUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>todo 字典管理接口实现类</p>
 * @author: andy.ten@tom.com | xukaixing@hotmail.com
 * @created: 2022/7/22 13:54
 * @version v1.0.1
 * @copyright: Copyright (c)  andyten
 */
@Service
public class SysDictServiceImpl implements SysDictService
{

  @Resource
  private SysDictMapper sysDictMapper;

  @Resource
  private TransResultService transResultService;

  @Resource
  private RedisDictFeignService redisDictFeignService;

  /**
   * <p>todo 获取父级字典列表</p>
   * @param: params
   * @return: com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map < java.lang.String, java.lang.Object>>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/22 13:54
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/22    andy.ten        v1.0.1             init
   */
  @Override
  public IPage<Map<String, Object>> findDictList(String params)
  {
    Page<Map<String, Object>> page = new Page<>();
    String conditions = MyUtil.getConditionsWhere(params, page);
    HashMap<String, String> transHash = new HashMap<>();
    // 设置排序
    OrderItem oi = new OrderItem();
    oi.setColumn("parent");
    oi.setAsc(true);
    List<OrderItem> al = page.getOrders();
    al.add(oi);
    page.setOrders(al);
    return transResultService.transResult(sysDictMapper.selectDictList(conditions, page), transHash);
  }

  /**
   * <p>todo 根据父级ID获取子级列表</p>
   * @param
   * @return: com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map < java.lang.String, java.lang.Object>>
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/1 13:57
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/1 guohao v1.0.1 init
   */
  @Override
  public IPage<Map<String, Object>> findChildListByParent(String params)
  {
    Page<Map<String, Object>> page = new Page<>();
    String conditions = MyUtil.getConditionsWhere(params, page);
    HashMap<String, String> transHash = new HashMap<>();
    transHash.put("isLeaf", "dic|sf");
    return transResultService.transResult(sysDictMapper.selectChildListByParent(conditions, page), transHash);
  }

  /**
   * <p>todo 字典管理父级字典新增</p>
   * @param param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/1 17:35
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/1 guohao v1.0.1 init
   */
  @Override
  public Map<String, Object> saveDictParent(Map<String, Object> param)
  {
    SysDictPO newParent = new SysDictPO();
    Map2ObjUtil.toObject(param, newParent);
    //非空校验
    this.checkDictParentIsEmpty(newParent, 0);
    //重复性校验
    this.checkDictParentRepetition(newParent);
    newParent.setParent(sysDictMapper.selectMaxParentCode() + 100);
    sysDictMapper.insert(newParent);
    List<SysDictPO> dataList = new ArrayList<>();
    dataList.add(newParent);
    redisDictFeignService.saveOrUpdateBatchDict(dataList);
    return param;
  }

  /**
   * <p>todo 字典管理父级字典修改</p>
   * @param parent
   * @param param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/1 17:10
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/1 guohao v1.0.1 init
   * 2022/7/5 guohao v1.0.2 init 去除非空校验操作类型
   */
  @Override
  public Map<String, Object> updateDictParent(Long parent, Map<String, Object> param)
  {
    //转换传入Code
    SysDictPO newParent = new SysDictPO();
    Map2ObjUtil.toObject(param, newParent);

    //非空校验
    this.checkDictParentIsEmpty(newParent, 1);
    //编辑重复性校验
    this.checkDictParentRepetition(newParent);

    //根据ID查询旧版Code
    LambdaQueryWrapper<SysDictPO> parentQuery = new LambdaQueryWrapper<>();
    parentQuery.eq(SysDictPO::getParent, parent);
    List<SysDictPO> parentList = sysDictMapper.selectList(parentQuery);

    //批量修改
    try
    {
      for (SysDictPO entity : parentList)
      {
        newParent.setId(entity.getId());
        entity.setParent(newParent.getParent());
        entity.setType(newParent.getType());
        entity.setTypeName(newParent.getTypeName());
      }
      sysDictMapper.updateBatch(parentList, SysDictPO.class);

    } catch (Exception e)
    {
      e.printStackTrace();
    }
    return param;
  }

  /**
   * <p>todo 父级字典项变更/添加重复性校验</p>
   * @param newParent
   * @return: void
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/4 14:55
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/4 guohao v1.0.1 init
   */
  private void checkDictParentRepetition(SysDictPO newParent)
  {
    StringBuffer whereSql = new StringBuffer();
    whereSql.append("(type_name = \"" + newParent.getTypeName());
    whereSql.append("\" and type = \"" + newParent.getType() + "\") ");
    List<Map<String, Object>> dictList = sysDictMapper.selectDictByWhere(whereSql.toString());
    if (!dictList.isEmpty())
    {
      AssertMyUtil.errMsg(BizCode.DICT_EXISTED);
    }
  }

  /**
   * <p>todo 父级字典项参数非空校验</p>
   * @param newParent
   * @param operateType: 操作类型新增与修改公用方法，0：新增，1：修改
   * @return: void
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/4 16:01
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/4 guohao v1.0.1 init
   * 2022/7/5 guohao v1.0.2 init 非空校验添加操作类型
   */
  private void checkDictParentIsEmpty(SysDictPO newParent, int operateType)
  {
    if (operateType == 1)
    {
      AssertMyUtil.notNull(newParent.getParent(), BizCode.VARIABLE_NOT_EMPTY, "parent");
    }
    AssertMyUtil.notEmpty(newParent.getType(), BizCode.VARIABLE_NOT_EMPTY, "type");
    AssertMyUtil.notEmpty(newParent.getTypeName(), BizCode.VARIABLE_NOT_EMPTY, "parent");
  }

  /**
   * <p>todo 删除父级字典（包括所属子字典项）</p>
   * @param parent
   * @return: boolean
   * @author: guohao | 2607728024@qq.com
   * @date: 2022/7/1 17:50
   * @version: 1.0.1
   * Modification History:
   * Date Author Version Description
   * -----------------------------------------------------------
   * 2022/7/1 guohao v1.0.1 init
   */
  @Override
  public boolean removeDictParent(Long parent)
  {
    LambdaQueryWrapper<SysDictPO> parentQuery = new LambdaQueryWrapper<>();
    parentQuery.eq(SysDictPO::getParent, parent);
    List<SysDictPO> parentList = sysDictMapper.selectList(parentQuery);
    for (SysDictPO entity : parentList)
    {
      entity.setStatus(100202);
      entity.setLastUpdateTime(LocalDateTime.now());
    }
    return sysDictMapper.updateBatch(parentList, SysDictPO.class);
  }

  /**
   * <p>todo 新增子级字典项</p>
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/22 14:39
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/22    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> saveDictChild(Map<String, Object> param)
  {
    SysDictPO sysDictPO = Map2ObjUtil.toObject(param, SysDictPO.class);
    AssertMyUtil.notNull(MyUtil.getValue(param.get("code")), BizCode.VARIABLE_NOT_EMPTY, "dicCode");
    AssertMyUtil.notNull(MyUtil.getValue(param.get("parent")), BizCode.VARIABLE_NOT_EMPTY, "parent");
    // 判断字典代码是否已存在
    List<Map<String, Object>> list = sysDictMapper.selectDictByCode(sysDictPO.getDicCode());
    if (list.size() > 0)
    {
      AssertMyUtil.errMsg("字典代码已存在.");
    }
    sysDictMapper.save(sysDictPO);
    // 绑定字典
    HashMap<String, String> transHash = new HashMap<>();
    Map<String, Object> result = transResultService.transResult(sysDictPO.toMaps(), transHash);
    // todo: 同步redis
    redisDictFeignService.syncDictItem(sysDictPO);
    return result;
  }

  /**
   * <p>todo 字典管理子级字典项修改</p>
   * @param: id
   * @param: param
   * @return: java.util.Map<java.lang.String, java.lang.Object>
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/22 13:24
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/22    andy.ten        v1.0.1             init
   */
  @Override
  public Map<String, Object> updateDictChild(Long id, Map<String, Object> param)
  {
    AssertMyUtil.notNull(id, BizCode.METHOD_ARGS_NOTNULL, "id");
    AssertMyUtil.notNull(MyUtil.getValue(param.get("code")), BizCode.VARIABLE_NOT_EMPTY, "dicCode");
    AssertMyUtil.notNull(MyUtil.getValue(param.get("parent")), BizCode.VARIABLE_NOT_EMPTY, "parent");
    SysDictPO sysDictPO = sysDictMapper.selectById(id);
    Map2ObjUtil.toObject(param, sysDictPO);
    sysDictMapper.updateById(sysDictPO);
    HashMap<String, String> transHash = new HashMap<>();
    Map<String, Object> result = transResultService.transResult(sysDictPO.toMaps(), transHash);
    // todo: 同步redis
    redisDictFeignService.syncDictItem(sysDictPO);
    return result;
  }

  /**
   * <p>todo 子级字典项移除</p>
   * @param: id
   * @return: boolean
   * @author: andy.ten@tom.com | xukaixing@hotmail.com
   * @date: 2022/7/22 15:22
   * @version: 1.0.1
   * Modification History:
   * Date         Author          Version            Description
   * -----------------------------------------------------------
   * 2022/7/22    andy.ten        v1.0.1             init
   */
  @Override
  public boolean removeChildDict(Long id, String dicType, String dicCode)
  {
    LambdaQueryWrapper<SysDictPO> lambdaQuery = Wrappers.lambdaQuery();
    lambdaQuery.eq(SysDictPO::getId, id);
    boolean result = sysDictMapper.remove(lambdaQuery);
    // todo: 同步redis
    redisDictFeignService.removeDictItem(dicType, dicCode);
    return result;
  }
}
